/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.yami.shop.bean.bo.flow.UserOrderStatisticBO;
import com.yami.shop.bean.dto.flow.CustomerRetainedDTO;
import com.yami.shop.bean.dto.flow.MemberReqDTO;
import com.yami.shop.bean.param.MemberOverviewParam;
import com.yami.shop.bean.param.MemberReqParam;
import com.yami.shop.bean.param.MemberSurveyRespParam;
import com.yami.shop.bean.vo.flow.*;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.UserLevelType;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.DateParam;
import com.yami.shop.common.util.DateUtils;
import com.yami.shop.common.util.PoiExcelUtil;
import com.yami.shop.dao.CustomerAnalysisMapper;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.dao.UserExtensionMapper;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.service.CustomerAnalysisService;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/10/26.
 */
@Slf4j
@Service
public class CustomerAnalysisServiceImpl implements CustomerAnalysisService {

    @Autowired
    private CustomerAnalysisMapper customerAnalysisMapper;

    @Autowired
    private UserExtensionMapper userExtensionMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private MapperFacade mapperFacade;

    @Override
    public MemberSurveyRespParam generalize(MemberReqParam memberReqParam) {
        MemberSurveyRespParam memberSurveyRespParam = new MemberSurveyRespParam();
        //统计比例数据
        Date startTime = null;
        //时间类型 1今日实时 2 近7天 3 近30天 4自然日 5自然月
        switch (memberReqParam.getDateType()){
            case 2:startTime = DateUtil.offsetDay(memberReqParam.getStartTime(),-7); break;
            case 3:startTime = DateUtil.offsetDay(memberReqParam.getStartTime(),-30); break;
            case 4:startTime = DateUtil.offsetDay(memberReqParam.getStartTime(),-30); break;
            default:startTime = DateUtil.offsetDay(memberReqParam.getStartTime(),-1);
        }
        List<MemberOverviewParam> customerRespParam = customerAnalysisMapper.generalize(startTime,memberReqParam);
        customerRespParam.sort(Comparator.comparingInt(MemberOverviewParam::getDataType));
        MemberOverviewParam memberOverviewParam = customerRespParam.get(0);
        getUserGeneralizeRate(memberOverviewParam,customerRespParam.get(1));
        memberSurveyRespParam.setMemberOverviewModel(memberOverviewParam);

        return memberSurveyRespParam;
    }

	@Override
	public MemberSurveyRespVO getMemberSurvey(MemberReqDTO param) {
        param.setShopId(Constant.PLATFORM_SHOP_ID);
        MemberSurveyRespVO memberSurveyRespVO = new MemberSurveyRespVO();
        memberSurveyRespVO.setMemberOverviewModelList(getMemberAnalysisSurvey(param));
        // 统计比例数据,获取到时间对比，新的会员数据截止时间为结束时间，旧会员数据截止时间为开始时间
        Date startTime = null;
        //时间类型 1今日实时 2 近7天 3 近30天 4自然日 5自然月
        switch (param.getDateType()){
            case 1:startTime = DateUtil.offsetDay(param.getStartTime(),-7); break;
            case 3:startTime = DateUtil.offsetDay(param.getStartTime(),-30); break;
            case 4:startTime = DateUtil.offsetDay(param.getStartTime(),-30); break;
            default:startTime = DateUtil.offsetDay(param.getStartTime(),-1);
        }
        param.setDateTime(null);
        // 获取新会员订单相关数据
        MemberOverviewVO newMemberOverviewVO = getMemberSurveyRespData(param);
        // 获取旧会员订单相关数据
        param.setEndTime(param.getStartTime());
        param.setStartTime(startTime);
        MemberOverviewVO oldMemberOverviewVO = getMemberSurveyRespData(param);

        getGeneralizeRate(newMemberOverviewVO,oldMemberOverviewVO);
        memberSurveyRespVO.setMemberOverviewModel(newMemberOverviewVO);
		return memberSurveyRespVO;
	}

    @Override
    public List<MemberTrendRespVO> getMemberTrend(MemberReqDTO param) {
        List<MemberTrendRespVO> resList = new ArrayList<>();
        Date startTime = param.getStartTime();
        Date endTime = param.getEndTime();
        List<DateParam> everyDays = DateUtils.findEveryDays(startTime, endTime);
        int total = 0;
        for (DateParam everyDay : everyDays) {
            MemberTrendRespVO res = new MemberTrendRespVO();
            param.setDateTime(null);
            param.setStartTime(everyDay.getStartTime());
            param.setEndTime(everyDay.getEndTime());
            res.setCurrentDay(DateUtils.dateToNumber(everyDay.getStartTime()));
            // 筛选时间类的每一天注册的会员数数据，不是每一天平台的总会员数
            Integer memberNum = userMapper.getMemberTrend(param);
            res.setMemberNum(Objects.isNull(memberNum) ? 0 : memberNum);
            total = total + res.getMemberNum();
            resList.add(res);
        }
        for (MemberTrendRespVO respParam : resList) {
            respParam.setMemberNumRate(Arith.div(respParam.getMemberNum(),total,4));
        }
        return resList;
    }

    @Override
    public MemberContributeRespVO getMemberContributeValue(MemberReqDTO param) {
        MemberContributeRespVO memberContributeRespVO = new MemberContributeRespVO();
        MemberContributeValueVO publicMember = userMapper.getMemberContributeValue(param, UserLevelType.ORDINARY.value());
        MemberContributeValueVO paidMember = userMapper.getMemberContributeValue(param, UserLevelType.ORDINARY.value());
        memberContributeRespVO.setPublicMember(publicMember);
        memberContributeRespVO.setPaidMember(paidMember);

        // 占比信息
        publicMember.setTotalMemberRate(Arith.div(publicMember.getTotalMember(),publicMember.getTotalMember()+paidMember.getTotalMember(),4));
        paidMember.setTotalMemberRate(Arith.sub(1,publicMember.getTotalMemberRate()));
        publicMember.setPayMemberNumRate(Arith.div(publicMember.getPayMemberNum(),publicMember.getPayMemberNum()+ paidMember.getPayMemberNum(),4));
        paidMember.setPayMemberNumRate(Arith.sub(1,publicMember.getPayMemberNumRate()));
        publicMember.setPayAmountRate(Arith.div(publicMember.getPayAmount(),Arith.add(publicMember.getPayAmount(),paidMember.getPayAmount()),4));
        paidMember.setPayAmountRate(Arith.sub(1,publicMember.getPayAmountRate()));

        memberContributeRespVO.setPublicMember(publicMember);
        memberContributeRespVO.setPaidMember(paidMember);
        return memberContributeRespVO;
    }

    @Override
    public MemberDealRespVO getMemberDeal(MemberReqDTO param) {
        MemberDealRespVO respParam = new MemberDealRespVO();
        List<MemberDealTreadVO> trend = new ArrayList<>();
        Date startTime = param.getStartTime();
        Date endTime = param.getEndTime();
        Date beforeYear = DateUtils.getBeforeYear(startTime, -2);
        param.setBeforeYear(beforeYear);
        param.setDateTime(null);
        param.setDayStartTime(startTime);
        // 获取会员成交数据
        // 支付客户数
        MemberDealVO allMember = new MemberDealVO();
        List<MemberDealVO> oldMemberDealList = customerAnalysisMapper.getMemberPayData(param, 0);
        List<MemberDealVO> newMemberDealList = customerAnalysisMapper.getMemberPayData(param, 1);
        MemberDealVO oldMember = getMemberPayInfo(oldMemberDealList);
        MemberDealVO newMember = getMemberPayInfo(newMemberDealList);

        allMember.setPayMemberNum(oldMemberDealList.size() + newMemberDealList.size());
        // 成交会员占比
        Integer payMemberNum = allMember.getPayMemberNum();
        allMember.setPayMemberNumRate(1.0);
        newMember.setPayMemberNumRate(Arith.div(newMember.getPayMemberNum(),payMemberNum,4));
        oldMember.setPayMemberNumRate(Arith.div(oldMember.getPayMemberNum(),payMemberNum,4));
        // 付款金额,占比
        allMember.setPayAmount(Arith.add(oldMember.getPayAmount(),newMember.getPayAmount()));
        allMember.setPayAmountRate(1.0);
        newMember.setPayAmountRate(Arith.div(newMember.getPayAmount(),allMember.getPayAmount(),4));
        oldMember.setPayAmountRate(Arith.sub(allMember.getPayAmountRate(),newMember.getPayAmountRate()));
        // 客单价
        allMember.setPricePerMember(Arith.div(allMember.getPayAmount(),allMember.getPayMemberNum(),2));
        // 支付订单数
        allMember.setPayOrderNum(newMember.getPayOrderNum() + oldMember.getPayOrderNum());
        respParam.setAllMember(allMember);
        respParam.setNewMember(newMember);
        respParam.setOldMember(oldMember);
        List<DateParam> everyDays = DateUtils.findEveryDays(startTime, endTime);
        for (DateParam everyDay : everyDays) {
            Date dayStartTime = everyDay.getStartTime();
            param.setStartTime(everyDay.getStartTime());
            param.setEndTime(everyDay.getEndTime());
            MemberDealTreadVO res = new MemberDealTreadVO();
            // 获取会员成交数据
            List<MemberDealVO> oldMemberDealItem = customerAnalysisMapper.getMemberPayData(param, 0);
            List<MemberDealVO> newMemberDealItem = customerAnalysisMapper.getMemberPayData(param, 1);
            MemberDealVO oldMemberItem = getMemberPayInfo(oldMemberDealItem);
            MemberDealVO newMemberItem = getMemberPayInfo(newMemberDealItem);
            res.setCurrentDay(DateUtils.dateToNumber(dayStartTime));
            // 支付会员数
            res.setOldPayMemberNum(oldMemberItem.getPayMemberNum());
            res.setNewPayMemberNum(newMemberItem.getPayMemberNum());
            // 支付订单数
            res.setNewPayOrderNum(newMemberItem.getPayOrderNum());
            res.setOldPayOrderNum(oldMemberItem.getPayOrderNum());
            // 支付金额
            res.setOldPayAmount(oldMemberItem.getPayAmount());
            res.setNewPayAmount(newMemberItem.getPayAmount());
            // 客单价
            res.setOldPricePerMember(Arith.div(res.getOldPayAmount(),res.getOldPayMemberNum(),2));
            res.setNewPricePerMember(Arith.div(res.getNewPayAmount(),res.getNewPayMemberNum(),2));
            trend.add(res);
        }
        respParam.setTrendParam(trend);
        return respParam;
    }

    @Override
    public List<CustomerRetainVO> getTradeRetained(CustomerRetainedDTO customerRetainedDTO) {
        List<CustomerRetainVO> tradeRetained = customerAnalysisMapper.getTradeRetained(customerRetainedDTO);
        return retainedAnalysis(tradeRetained, customerRetainedDTO);
    }

    @Override
    public void memberTrendExport(MemberReqDTO param, HttpServletResponse response) {
        param.setMemberType(1);
        List<MemberTrendRespVO> ordinaryMember = getMemberTrend(mapperFacade.map(param, MemberReqDTO.class));
        param.setMemberType(2);
        List<MemberTrendRespVO> payMember = getMemberTrend(mapperFacade.map(param, MemberReqDTO.class));

        // 存入excel中
        //通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getBigWriter();
        // 商品导出or模板
        String[] headerArray = {"日期", "普通会员增加人数", "付费会员增加人数"};
        List<String> headerList = Arrays.asList(headerArray);
        writer.merge(headerList.size() - 1, "会员人数趋势信息");
        writer.writeRow(headerList);
        Sheet sheet = writer.getSheet();
        sheet.setColumnWidth(0, 40 * 256);
        sheet.setColumnWidth(1, 40 * 256);
        sheet.setColumnWidth(2, 40 * 256);
        Map<Long, Integer> payMemberMap = payMember.stream().collect(Collectors.toMap(MemberTrendRespVO::getCurrentDay, MemberTrendRespVO::getMemberNum));
        try {
            int row = 1;
            // 写入excel
            for (MemberTrendRespVO memberTrendRespVO : ordinaryMember) {
                int col = -1;
                Date date = DateUtil.parse(memberTrendRespVO.getCurrentDay().toString(), "yyyyMMdd");
                PoiExcelUtil.mergeIfNeed(writer, ++row, row, ++col, col, DateUtil.format(date, "yyyy-MM-dd"));

                PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, memberTrendRespVO.getMemberNum());
                PoiExcelUtil.mergeIfNeed(writer, row, row, ++col, col, payMemberMap.get(memberTrendRespVO.getCurrentDay()));
            }
            PoiExcelUtil.writeExcel(response, writer);
        } catch (Exception e) {
            log.error("Exception:", e);
        }
    }

    private List<CustomerRetainVO> retainedAnalysis(List<CustomerRetainVO> tradeRetained, CustomerRetainedDTO customerRetainedDTO) {
        Date startTime = customerRetainedDTO.getStartTime();
        Map<String, List<CustomerRetainVO>> map = new HashMap<>(12);
        if (CollUtil.isNotEmpty(tradeRetained)) {
            map = tradeRetained.stream().collect(Collectors.groupingBy(CustomerRetainVO::getCurrentMonth));
        }
        List<CustomerRetainVO> list = new ArrayList<>();
        while (startTime.getTime() < customerRetainedDTO.getEndTime().getTime()) {
            String startDate = DateUtil.year(startTime) + "-" + (DateUtil.month(startTime) + 1);
            List<CustomerRetainVO> customerRetainVOS = map.get(startDate);
            CustomerRetainVO customerRetainVO = new CustomerRetainVO();
            customerRetainVO.setCurrentMonth(startDate);
            Map<Integer, Integer> collect;
            if(CollUtil.isNotEmpty(customerRetainVOS)) {
                collect = customerRetainVOS.stream().collect(Collectors.toMap(CustomerRetainVO::getMonth, CustomerRetainVO::getNewCustomers));
            } else {
                collect = new HashMap<>(16);
            }
            // 保留位数
            int scale = 2;
            // 放大倍数
            Integer percentage = 100;
            Integer newCustomers = getNewCustomers(collect, 0);
            customerRetainVO.setNewCustomers(newCustomers);
            customerRetainVO.setFifthMonthRemain(newCustomers);
            customerRetainVO.setFirstMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getFirstMonthRemain(),newCustomers,scale, percentage));
            customerRetainVO.setSecondMonthRemain(getNewCustomers(collect, 1));
            customerRetainVO.setSecondMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getSecondMonthRemain(),newCustomers,scale, percentage));
            customerRetainVO.setThirdMonthRemain(getNewCustomers(collect, 2));
            customerRetainVO.setThirdMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getThirdMonthRemain(),newCustomers,scale, percentage));
            customerRetainVO.setFourthMonthRemain(getNewCustomers(collect, 3));
            customerRetainVO.setFourthMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getFourthMonthRemain(),newCustomers,scale, percentage));
            customerRetainVO.setFifthMonthRemain(getNewCustomers(collect, 4));
            customerRetainVO.setFifthMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getFirstMonthRemain(),newCustomers,scale, percentage));
            customerRetainVO.setSixthMonthRemain(getNewCustomers(collect, 5));
            customerRetainVO.setSixthMonthRemainRate(Arith.calculatePercentage(customerRetainVO.getSixthMonthRemain(),newCustomers,scale, percentage));
            list.add(customerRetainVO);
            startTime = DateUtil.offsetMonth(startTime, 1);
        }
        return list;
    }

    private int getNewCustomers(Map<Integer, Integer> collect, int i) {
        if (collect.containsKey(i)) {
            return collect.get(i);
        }
        return 0;
    }

    private MemberDealVO getMemberPayInfo(List<MemberDealVO> memberDealList) {
        MemberDealVO memberDealVO = new MemberDealVO();
        if(CollUtil.isEmpty(memberDealList)){
            memberDealVO.setPayMemberNum(0);
            memberDealVO.setPayAmount(0.00);
            memberDealVO.setPricePerMember(0.00);
            memberDealVO.setPayOrderNum(0);
        } else {
            memberDealVO.setPayMemberNum(memberDealList.size());
            // 支付金额
            Double payAmount = memberDealList.stream().mapToDouble(MemberDealVO::getPayAmount).sum();
            memberDealVO.setPayAmount(payAmount);
            // 支付订单数
            memberDealVO.setPricePerMember(Arith.div(memberDealVO.getPayAmount(), memberDealVO.getPayMemberNum(), 2));
            Integer payOrderCount = memberDealList.stream().mapToInt(MemberDealVO::getPayOrderNum).sum();
            memberDealVO.setPayOrderNum(payOrderCount);
        }
        return memberDealVO;
    }

    private MemberOverviewVO getMemberSurveyRespData(MemberReqDTO param) {
        MemberOverviewVO memberOverviewVO = userMapper.getMemberAnalysisByParam(param);
        memberOverviewVO.setMemberSingleAmount(Arith.div(memberOverviewVO.getMemberPayAmount(), memberOverviewVO.getPayMember(), 2));
        return memberOverviewVO;
    }

    private void getGeneralizeRate(MemberOverviewVO memberOverviewVO, MemberOverviewVO oldMemberOverviewVO){
        memberOverviewVO.setMemberSingleAmount(Arith.div(memberOverviewVO.getMemberPayAmount(),memberOverviewVO.getPayMember(),2));
        oldMemberOverviewVO.setMemberSingleAmount(Arith.div(oldMemberOverviewVO.getMemberPayAmount(),oldMemberOverviewVO.getPayMember(),2));
        memberOverviewVO.setTotalMemberRate(setRate(memberOverviewVO.getTotalMember().doubleValue(),oldMemberOverviewVO.getTotalMember().doubleValue()));
        memberOverviewVO.setNewMemberRate(setRate(memberOverviewVO.getNewMember().doubleValue(),oldMemberOverviewVO.getNewMember().doubleValue()));
        memberOverviewVO.setCouponMemberRate(setRate(memberOverviewVO.getCouponMember().doubleValue(),oldMemberOverviewVO.getCouponMember().doubleValue()));
        memberOverviewVO.setPayMemberRate(setRate(memberOverviewVO.getPayMember().doubleValue(),oldMemberOverviewVO.getPayMember().doubleValue()));
        memberOverviewVO.setMemberPayAmountRate(setRate(memberOverviewVO.getMemberPayAmount(),oldMemberOverviewVO.getMemberPayAmount()));
        memberOverviewVO.setMemberPayOrderRate(setRate(memberOverviewVO.getMemberPayOrder().doubleValue(),oldMemberOverviewVO.getMemberPayOrder().doubleValue()));
        memberOverviewVO.setMemberSingleAmountRate(setRate(memberOverviewVO.getMemberSingleAmount(),oldMemberOverviewVO.getMemberSingleAmount()));
    }

    private MemberOverviewVO getUserOrderBO(MemberReqDTO param, Date startTime, Date endTime ) {
        List<UserOrderStatisticBO> userOrderList;
        // 获取到条件内每个用户的支付金额，支付订单数（同时运算下获取其他的数据）
        userOrderList = orderMapper.getPaidMemberByParam(param);
        MemberOverviewVO res = userExtensionMapper.getMemberOverviewVO(param, startTime, endTime);
        res.setCurrentDay(DateUtils.dateToNumber(param.getStartTime()));
        if(CollUtil.isEmpty(res.getUserIds())){
            // 会员支付金额
            res.setMemberPayAmount(0.00);
            // 会员支付订单数
            res.setMemberPayOrder(0);
            // 会员客单价
            res.setMemberSingleAmount(0.0);
            // 支付会员数
            res.setPayMember(0);

        } else {
            // 如果不为0则筛选一下当前满足条件的用户
            if (!Objects.equals(param.getMemberType(), 0)) {
                List<Long> userDbIds = res.getUserIds();
                // 筛选交集的用户
                userOrderList = userOrderList.stream().filter(userOrder->userDbIds.contains(
                        userOrder.getUserId())).collect(Collectors.toList());
            }
            double sumAmount = userOrderList.stream().mapToDouble(UserOrderStatisticBO::getActualAmount).sum();
            Integer sumPayOrderCount = userOrderList.stream().mapToInt(UserOrderStatisticBO::getConsTimes).sum();
            // 会员支付金额
            res.setMemberPayAmount(handDouble(sumAmount));
            // 支付会员数
            res.setPayMember(userOrderList.size());
            // 会员支付订单数
            res.setMemberPayOrder(sumPayOrderCount);
            // 会员客单价
            res.setMemberSingleAmount(Arith.div(res.getMemberPayAmount(), userOrderList.size(), 2));
        }
        // 领券会员数
        res.setCouponMember(customerAnalysisMapper.countMemberCouponByParam(param));
        return res;
    }

    private List<MemberOverviewVO> getMemberAnalysisSurvey(MemberReqDTO param) {
        Date startTime = param.getStartTime();
        Date endTime = param.getEndTime();
        List<DateParam> everyDays = DateUtils.findEveryDays(startTime,endTime);
        List<MemberOverviewVO> resList = new ArrayList<>();
        if (Objects.isNull(param.getMemberType())){
            param.setMemberType(0);
        }
        if (everyDays.size() == 1 ) {
            Date beforeDate = DateUtils.getBeforeDate(everyDays.get(0).getStartTime());
            everyDays = DateUtils.findEveryDays(beforeDate, param.getEndTime());
        }
        MemberOverviewVO memberOverviewVO;
        for (DateParam everyDay : everyDays) {
            // 支付会员数，再筛选时间内，购买商品的会员人数
            // 先查询用户（可能有几十万用户ids）再根据用户来查询订单不行，需要先查订单在进行筛选
            param.setDateTime(null);
            param.setStartTime(DateUtil.beginOfDay(startTime));
            param.setEndTime(DateUtil.endOfDay(endTime));
            // 获取订单相关用户信息
            memberOverviewVO = getUserOrderBO(param, everyDay.getStartTime(),everyDay.getEndTime());

            resList.add(memberOverviewVO);
        }
        return resList;
    }

	private void getUserGeneralizeRate(MemberOverviewParam memberOverviewParam,MemberOverviewParam oldMemberOverviewParam){
        memberOverviewParam.setMemberSingleAmount(Arith.div(memberOverviewParam.getMemberPayAmount(),memberOverviewParam.getPayMember(),2));
        oldMemberOverviewParam.setMemberSingleAmount(Arith.div(oldMemberOverviewParam.getMemberPayAmount(),oldMemberOverviewParam.getPayMember(),2));
        memberOverviewParam.setTotalMemberRate(setRate(memberOverviewParam.getTotalMember().doubleValue(),oldMemberOverviewParam.getTotalMember().doubleValue()));
        memberOverviewParam.setNewMemberRate(setRate(memberOverviewParam.getNewMember().doubleValue(),oldMemberOverviewParam.getNewMember().doubleValue()));
        memberOverviewParam.setCouponMemberRate(setRate(memberOverviewParam.getCouponMember().doubleValue(),oldMemberOverviewParam.getCouponMember().doubleValue()));
        memberOverviewParam.setPayMemberRate(setRate(memberOverviewParam.getPayMember().doubleValue(),oldMemberOverviewParam.getPayMember().doubleValue()));
        memberOverviewParam.setMemberPayAmountRate(setRate(memberOverviewParam.getMemberPayAmount(),oldMemberOverviewParam.getMemberPayAmount()));
        memberOverviewParam.setMemberPayOrderRate(setRate(memberOverviewParam.getMemberPayOrder().doubleValue(),oldMemberOverviewParam.getMemberPayOrder().doubleValue()));
        memberOverviewParam.setMemberSingleAmountRate(setRate(memberOverviewParam.getMemberSingleAmount(),oldMemberOverviewParam.getMemberSingleAmount()));

    }

    /**
     * 设置普通会员or付费会员数据的订单相关数据（支付会员数、支付金额、支付订单数、人均消费频次、客单价、人均消费频次）
     * @param userOrderInfoList 会员订单相关数据
     * @param userIds 筛选出的符合条件userIds
     * @param memberContributeValueVO 普通会员or付费会员数据
     */
    private void setUserOrderData(List<UserOrderStatisticBO> userOrderInfoList, List<String> userIds, MemberContributeValueVO memberContributeValueVO) {
        List<UserOrderStatisticBO> userOrderList;
        // TODO 支付频次暂不统计 时间段内：支付订单数 / 消费人数
        if(CollectionUtil.isEmpty(userIds)){
            // 支付会员数
            memberContributeValueVO.setPayMemberNum(0);
            // 支付金额
            memberContributeValueVO.setPayAmount(0.00);
            // 会员支付订单数
            memberContributeValueVO.setPayOrderNum(0);
            // 会员客单价
            memberContributeValueVO.setPricePerMember(0.00);
            // 人均消费频次
            memberContributeValueVO.setFrequencyOfConsume(0.0);
        }else {
            // 筛选交集的用户
            userOrderList = userOrderInfoList.stream().filter(userOrder->userIds.contains(
                    userOrder.getUserId())).collect(Collectors.toList());
            Double sumAmount = userOrderList.stream().mapToDouble(UserOrderStatisticBO::getActualAmount).sum();
            Integer sumPayOrderCount = userOrderList.stream().mapToInt(UserOrderStatisticBO::getConsTimes).sum();
            // 会员支付人数
            memberContributeValueVO.setPayMemberNum(userOrderList.size());
            // 会员支付金额
            memberContributeValueVO.setPayAmount(sumAmount);
            // 会员支付订单数
            memberContributeValueVO.setPayOrderNum(sumPayOrderCount);
            // 会员客单价
            memberContributeValueVO.setPricePerMember(Arith.div(memberContributeValueVO.getPayAmount(), memberContributeValueVO.getPayMemberNum(), 4));
            // 人均消费频次
            memberContributeValueVO.setFrequencyOfConsume(Arith.div(memberContributeValueVO.getPayOrderNum(), memberContributeValueVO.getPayMemberNum(),2));
        }
    }

    private Double setRate(Double newNum,Double oldNum){
        if (newNum.equals(0.0) && oldNum.equals(0.0)){
            return 0.0;
        }else if (newNum > 0.0 && oldNum.equals(0.0)){
            return 0.0;
        }else if (newNum.equals(0.0) && oldNum > 0.0){
            return -100.0;
        }
        double sub = Arith.sub(newNum, oldNum);
        return Arith.mul(Arith.div(sub,oldNum,2),100);
    }

    private Double handDouble(Double value){
        if (Objects.isNull(value)){
            return 0.00;
        }
        return value;
    }
}
